package edu.kpi.pzks2.ui.task;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;

import edu.kpi.pzks2.graph.Edge;
import edu.kpi.pzks2.graph.GraphBundle;
import edu.kpi.pzks2.graph.Node;
import edu.kpi.pzks2.queue.NodeStatistDescriptor;
import edu.kpi.pzks2.tools.GenerationParams;
import edu.kpi.pzks2.ui.GraphEditor;
import edu.kpi.pzks2.ui.GraphMenuBarListeners;
import edu.kpi.pzks2.ui.GraphMenuBarListeners.LoadListener;
import edu.kpi.pzks2.ui.GraphToolBar;
import edu.kpi.pzks2.ui.MainFrame;
import edu.kpi.pzks2.ui.MainFrame.LoadLabel;
import edu.kpi.pzks2.ui.dialogs.GeneratorDialog;
import edu.uci.ics.jung.graph.DirectedGraph;

@SuppressWarnings("serial")
public class TaskFrame extends JFrame implements LoadListener<GraphBundle> {
    public static final String TITLE = "Task editor";
    
    public static final String QUEUE1ACT = "queue1";
    public static final String QUEUE2ACT = "queue2";
    public static final String QUEUE3ACT = "queue3";
    
    public static enum QueueType {
        QUEUE1, QUEUE2, QUEUE3
    }
    
    public static enum StrategyType {
        SIMPLE, PREEMPTIVE;
    }
    
    final TaskEditor graphEditor;
    
    private QueueType currentQueueType;
    
    public TaskFrame(final LoadLabel loadLabel) {
        setTitle(TITLE);

        setLayout(new BorderLayout());
        
        graphEditor = new TaskEditor();
        add(new JScrollPane(graphEditor), BorderLayout.CENTER);

        setJMenuBar(buildMenu(this, graphEditor));
        
        final JToolBar toolBar = new GraphToolBar(graphEditor, loadLabel);
        add(toolBar, BorderLayout.NORTH);
        
        final JButton queueButton = new JButton("Queue");
        toolBar.add(queueButton);
        queueButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                final List<NodeStatistDescriptor> descs = graphEditor.getNodeDescList();
                
                Comparator<NodeStatistDescriptor> comp = null;
                
                switch (currentQueueType) {
                case QUEUE1:
                    comp = new Comparator<NodeStatistDescriptor>() {
                        public int compare(NodeStatistDescriptor o1, NodeStatistDescriptor o2) {
                            // code smells...
                            if (o1.getNormalizedSum() == o2.getNormalizedSum()) {
                                return 0;
                            }
                            
                            if (o2.getNormalizedSum() - o1.getNormalizedSum() > 0) {
                                return 1;
                            } else {
                                return -1;
                            }
                        }
                    };
                    break;
                case QUEUE2:
                    comp = new Comparator<NodeStatistDescriptor>() {
                        public int compare(NodeStatistDescriptor o1, NodeStatistDescriptor o2) {
                                return o2.getCriticalPathLength() - o1.getCriticalPathLength();
                        }
                    };
                    break;
                case QUEUE3:
                    comp = new Comparator<NodeStatistDescriptor>() {
                        public int compare(NodeStatistDescriptor o1, NodeStatistDescriptor o2) {
                            if (o1.getLinksNum() == o2.getLinksNum()) {
                                return o2.getCriticalPathLength() - o1.getCriticalPathLength();
                            } else {
                                return o2.getLinksNum() - o1.getLinksNum();
                            }
                        }
                    };
                    break;
                }
                
                Collections.sort(descs, comp);
                
                for (NodeStatistDescriptor desc : descs) {
                    switch (currentQueueType) {
                    case QUEUE1:
                        MainFrame.showLogMessage(
                                String.format(
                                        "#%d Normalized sum = %f", desc.getNode().getId(), desc.getNormalizedSum()));
                        break;
                    case QUEUE2:
                        MainFrame.showLogMessage(
                                String.format(
                                        "#%d Critical path = %d", desc.getNode().getId(), 
                                        desc.getCriticalPathLength()));
                        break;
                    case QUEUE3:
                        MainFrame.showLogMessage(
                                String.format(
                                        "#%d Links = %d Critical path = %d",
                                        desc.getNode().getId(),
                                        desc.getLinksNum(),
                                        desc.getCriticalPathLength()));
                        break;
                    }
                }
                MainFrame.showLogMessage("#################\n");
            }
        });
        
        final JButton generateButton = new JButton("Generate");
        toolBar.add(generateButton);
        generateButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                new GeneratorDialog(TaskFrame.this).setVisible(true);
            }
        });
        
        setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        setBounds(100, 100, 450, 300);
    }
    
    private JMenuBar buildMenu(final Component parent, final GraphEditor graphEditor) {
        final JMenuBar menubar = new JMenuBar();
        
        final JMenu fileMenu = new JMenu("File");
        menubar.add(fileMenu);
        
        final JMenuItem openItem = new JMenuItem("Open");
        final JMenuItem saveItem = new JMenuItem("Save");
        final JMenuItem saveAsItem = new JMenuItem("Save as");
        
        openItem.addActionListener(GraphMenuBarListeners.getOpenListener(this, parent));
        saveItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                GraphMenuBarListeners.save(new GraphBundle(graphEditor.getGraphLayout()), parent);
            }
        });
        
        fileMenu.add(openItem);
        fileMenu.add(saveItem);
        fileMenu.add(saveAsItem);
        
        final JMenu queueMenu = new JMenu("Queue");
        menubar.add(queueMenu);
        
        final JMenuItem queue1Item = new JRadioButtonMenuItem("queue1");
        final JMenuItem queue2Item = new JRadioButtonMenuItem("queue2");
        final JMenuItem queue3Item = new JRadioButtonMenuItem("queue3");
        
        queue1Item.setSelected(true);
        currentQueueType = QueueType.QUEUE1;
        
        ButtonGroup group = new ButtonGroup();
        group.add(queue1Item);
        group.add(queue2Item);
        group.add(queue3Item);
        
        queue1Item.setActionCommand(QUEUE1ACT);
        queue2Item.setActionCommand(QUEUE2ACT);
        queue3Item.setActionCommand(QUEUE3ACT);
        
        queueMenu.add(queue1Item);
        queueMenu.add(queue2Item);
        queueMenu.add(queue3Item);

        final ActionListener radioListener = new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                if (arg0.getActionCommand().equals(QUEUE1ACT)) {
                    currentQueueType = QueueType.QUEUE1;
                    return;
                }
                
                if (arg0.getActionCommand().equals(QUEUE2ACT)) {
                    currentQueueType = QueueType.QUEUE2;
                    return;
                }
                
                if (arg0.getActionCommand().equals(QUEUE3ACT)) {
                    currentQueueType = QueueType.QUEUE3;
                    return;
                }
            }
        };
        
        queue1Item.addActionListener(radioListener);
        queue2Item.addActionListener(radioListener);
        queue3Item.addActionListener(radioListener);
        
        final JMenu helpMenu = new JMenu("Help");
        menubar.add(helpMenu);
        
        final JMenuItem helpItem = new JMenuItem("Help");
        helpMenu.add(helpItem);
        
        return menubar;
    }
    
    public QueueType getCurrentQueueType() {
        return currentQueueType;
    }
    
    public void generateGraph(final GenerationParams params) {
        graphEditor.generateGraph(params);
    }

    public void objectLoaded(GraphBundle loadedObject) {
        graphEditor.setGraphBundle(loadedObject);
    }
    
    public DirectedGraph<Node, Edge> getTaskGraph() {
        return graphEditor.getTaskGraph();
    }
}
